/*
 * MainPage.java
 *
 * Created on October 29, 2008, 6:26 PM
 */
//todo -> graphically show all processes at once, resources
package deadlocksim.gui;
import deadlocksim.*;
import deadlocksim.DeadlockSim.*;
import deadlocksim.gui.*;
import deadlocksim.backend.*;
import deadlocksim.backend.io.*;
import deadlocksim.backend.process.*;
import deadlocksim.backend.resources.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
/**
 *
 * @author  CCSCHMID
 * KarenPell added tooltip text, the resources button and it's actions.
 * KarenPell and romilian added the enabling/disabling of buttons based on program execution,
 * updated the action for the reset button, and added the Start Over button.
 */
public class MainPage extends JFrame {
    private ProcessEditorUI processEditorUI;
    private ResourceEditorUI resourceEditorUI;
    private DeadlockProcess deadlockProcess;
    private HaltAction pauseAction;
    private DeadlockSim sim;
    private DeadlockResourceDisplay resourceDisplay;
    private GradientButton processesButton,resourcesButton, runButton,stepButton,
            pauseButton, resetButton, clearSimButton;
    private GradientButton exitButton, helpButton;
    
    private GradientButton bankersAlgButton;
    
    private GradientButton loadQuickTestButton;
    private JPanel mainPanel, resourcePanel, importResourcePanel;
    private JScrollPane statusScrollPane;
    private JTextArea statusTextArea;
    //private step button
    
    String activateBankersText = "ACTIVATE Auto Deadlock Avoidance";
    String deactivateBankersText = "DEACTIVATE Auto Deadlock Avoidance";
    
    /** Creates new form MainPage */
    public MainPage() 
    {
        initComponents();
        
    }
    private void createNewSim()
    {
        this.sim = new DeadlockSim();
    }
    public void clearSimulator()
    {
        this.getContentPane().removeAll();
        //JTextArea textArea = this.getStatusTextArea();
        initComponents();
    }

    private void initComponents() 
    {
        createNewSim();
        mainPanel = new JPanel();
        mainPanel.setBackground(GuiConfig.MAIN_PANEL_COLOR);
        loadQuickTestButton = new GradientButton("Load Quick Test Scenario");
        processesButton = new GradientButton();
        resourcesButton = new GradientButton();
        bankersAlgButton = new GradientButton(this.activateBankersText);
        runButton = new GradientButton();
        runButton.setIcon("run.png");
        pauseButton = new GradientButton();
        pauseButton.setIcon("shutdown.png");
        stepButton = new GradientButton();
        resetButton = new GradientButton();
        clearSimButton = new GradientButton();
        exitButton = new GradientButton();
        helpButton = new GradientButton();
        statusScrollPane = new JScrollPane();
        statusTextArea = new JTextArea();
        //clockPanel = new JScrollPane();
        //clockTextArea = new JTextArea();
        resourcePanel = new JPanel();
        importResourcePanel = new JPanel();
        processesButton.setEnabled(false);
        runButton.setEnabled(false);
        pauseButton.setEnabled(false);
        stepButton.setEnabled(false);
        resetButton.setEnabled(false);
        
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        
        loadQuickTestButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent evt)
            {
                loadQuickTestScenario();
                //sim.refreshDisplay();
                //resourcesButton.setEnabled(false);
            }
        });

        processesButton.setText("Define Processes");
        processesButton.setToolTipText("Select this button to define the processes for the simulator.");
        processesButton.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent evt) 
            {
                processesButtonActionPerformed(evt);
                sim.refreshDisplay();
                runButton.setEnabled(true);
                stepButton.setEnabled(true);
            }
        });
        
        resourcesButton.setText("Define Resources");
        resourcesButton.setToolTipText("Select this button to define the resources for the simulator.");
        resourcesButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent evt)
            {
                resourcesButtonActionPerformed(evt);
                sim.refreshDisplay();
                processesButton.setEnabled(true);
                //startOverButton.setEnabled(true);
                //resourcesButton.setEnabled(false);
            }
        });
        
        this.bankersAlgButton.setToolTipText("Click to activate/deactivate the Banker's Deadlock Avoidance Algorithm");
        bankersAlgButton.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent evt) 
            {
                bankersAlgButtonActionPerformed(evt);

            }
        });

        //runButton.setText("Run");
        runButton.setToolTipText("Select this button to run the simulator.");
        runButton.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent evt) 
            {
                runButtonActionPerformed(evt);

            }
        });

        //pauseButton.setText("Pause");
        pauseButton.setToolTipText("Select this button to stop the simulator.");
        pauseButton.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent evt) 
            {
                pauseButtonActionPerformed(evt);
                runButton.setEnabled(true);  //Rafal added
                stepButton.setEnabled(true);
                pauseButton.setEnabled(false);
                resourcesButton.setEnabled(true);
                processesButton.setEnabled(true);
            }
        });

        stepButton.setText("Step");
        stepButton.setToolTipText("select this button to run the simulator one clock tick at a time.");
        stepButton.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent evt) 
            {
                stepButtonActionPerformed(evt);

            }
        });

        resetButton.setText("Reset Scenario");
        resetButton.setToolTipText("Select this button to reset the loaded scenario to time 0.");
        resetButton.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent evt) 
            {
                resetButtonActionPerformed(evt);
                stepButton.setEnabled(true);
                runButton.setEnabled(true);
                pauseButton.setEnabled(false);
            }
        });

        clearSimButton.setText("Clear Simulator");
        clearSimButton.setToolTipText("Select this button to start over from scratch.");
        clearSimButton.addActionListener(new ActionListener ()
        {
            public void actionPerformed(ActionEvent evt)
            {
                startOverButtonActionPerformed(evt);
                pauseButton.setEnabled(false);
                stepButton.setEnabled(false);
                resetButton.setEnabled(false);
                processesButton.setEnabled(false);
                runButton.setEnabled(false);            
                resourcesButton.setEnabled(true);
                //startOverButton.setEnabled(false);
            }
            
        });
        exitButton.setText("Exit");
        exitButton.setToolTipText("Select this button to exit the simuator.");
        exitButton.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent evt) 
            {
                exitButtonActionPerformed(evt);
            }
        });

        helpButton.setText("Help");
        helpButton.setToolTipText("Select this button to load the help file");
        helpButton.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent evt) 
            {
                helpButtonActionPerformed(evt);
            }
        });

        this.setTitle("Deadlock Simulator v.\u221E.0");
        //this.setTitle("Deadlock Simulator v.inf.0");
        
        mainPanel.setBorder(BorderFactory.createTitledBorder("DeadlockSim"));
        
        statusScrollPane.setBorder(BorderFactory.createTitledBorder("Updates"));

        //statusTextArea.setColumns(20);
        //statusTextArea.setRows(5);
        statusScrollPane.setViewportView(statusTextArea);
        
        //clockPanel.setBorder(BorderFactory.createTitledBorder("Clock Panel"));
        //clockPanel.setViewportView(clockTextArea);
                
        resourcePanel.setBorder(BorderFactory.createTitledBorder("Status"));
        resourcePanel.add((JPanel)(sim.getResourceDisplay()));
        
        GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
                    .addComponent(resourcesButton)
                    .addComponent(processesButton)
                    .addComponent(loadQuickTestButton)
                    .addComponent(pauseButton)
                    .addComponent(stepButton)
                    .addComponent(bankersAlgButton)
                    .addComponent(runButton)
                    .addComponent(resetButton)
                    .addComponent(clearSimButton)
                    .addComponent(exitButton)
                    .addComponent(helpButton))
                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
                    .addComponent(resourcePanel, GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
                    //.addComponent(clockPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(statusScrollPane, GroupLayout.PREFERRED_SIZE, 500, GroupLayout.PREFERRED_SIZE))
                    .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
                    
                    .addContainerGap(119, Short.MAX_VALUE))
                    //.addContainerGap())
        );

        mainPanelLayout.linkSize(SwingConstants.HORIZONTAL, new java.awt.Component[] {pauseButton, resourcesButton, processesButton, loadQuickTestButton, resetButton, clearSimButton, bankersAlgButton, runButton, stepButton});

        mainPanelLayout.linkSize(SwingConstants.HORIZONTAL, new java.awt.Component[] {exitButton, helpButton});

        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(resourcesButton)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(processesButton)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 20, Short.MAX_VALUE)
                        .addComponent(loadQuickTestButton)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 20, Short.MAX_VALUE)
                        .addComponent(bankersAlgButton)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(runButton)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(pauseButton)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(stepButton)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(resetButton)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 50, Short.MAX_VALUE)
                        .addComponent(clearSimButton)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 150, Short.MAX_VALUE)
                        //.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(helpButton)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(exitButton))
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)    
                        .addComponent(statusScrollPane, GroupLayout.PREFERRED_SIZE, 320, GroupLayout.PREFERRED_SIZE)
                        //.addComponent(statusScrollPane, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
                        //.addComponent(clockPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        //.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(resourcePanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap())
        );

        GroupLayout layout = new GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(mainPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                //.addContainerGap(105, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(mainPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        
        //this.statusScrollPane.setVisible(false);
        processEditorUI = new ProcessEditorUI(this);
        resourceEditorUI = new ResourceEditorUI(this);
        
        //this.statusTextArea.setText(textArea.getText());
        this.sim.setMainFrame(this);
        pack();
    }// </editor-fold>//GEN-END:initComponents
    public DeadlockSim getDeadlockSim()
    {
        return this.sim;
    }
    
    private void bankersAlgButtonActionPerformed(java.awt.event.ActionEvent evt)
    {
        ResourceManager rm = sim.getResourceManager();
        boolean newBankersMode = ! rm.getBankersMode();
        rm.setBankersDeadlockAvoidance(newBankersMode);
        
        if(newBankersMode == true)
            bankersAlgButton.setText(this.deactivateBankersText);
        else
            bankersAlgButton.setText(this.activateBankersText);
    }


    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
     // newProcessEditorPanel= new ProcessEditorUI(); 
      openProcesses();
    }//GEN-LAST:event_jButton2ActionPerformed
    void openProcesses(){

    
    }
    
    public JTextArea getStatusTextArea()
    {
        return statusTextArea;
    }
    
    private void loadQuickTestScenario()
    {
        
        sim.createResource(0);
        sim.createResource(1);
        sim.createResource(2);
        sim.createResource(3);
        
        ProcessAction request0 = new RequestResourceAction(0);
        ProcessAction request1 = new RequestResourceAction(1);
        ProcessAction request2 = new RequestResourceAction(2);
        
        ProcessAction free0 = new FreeResourceAction(0);
        ProcessAction free1 = new FreeResourceAction(1);
        ProcessAction free2 = new FreeResourceAction(2); 
        
        ProcessAction compute = new ComputeAction();
        
        ProcessAction halt = new HaltAction();
        
        Queue<ProcessAction> p1Actions = new LinkedList<ProcessAction>();
            p1Actions.add(compute);
            p1Actions.add(compute);
            p1Actions.add(request0); // Request 0
            p1Actions.add(compute); //Comput
            p1Actions.add(request1); // Request 1
            p1Actions.add(compute);
            p1Actions.add(compute);
            p1Actions.add(free1);
            p1Actions.add(compute);
            p1Actions.add(request2);
            p1Actions.add(compute);
            p1Actions.add(free0);
            p1Actions.add(free2);
            p1Actions.add(halt);
            
        Queue<ProcessAction> p2Actions = new LinkedList<ProcessAction>();
            p2Actions.add(compute);
            p2Actions.add(compute);
            p2Actions.add(request1); // Request 0
            p2Actions.add(compute); // Request 1
            p2Actions.add(request0); // Request 0
            p2Actions.add(compute); //Compute
            p2Actions.add(compute);
            p2Actions.add(compute);
            p2Actions.add(free0);
            p2Actions.add(compute);
            p2Actions.add(free1);
            p2Actions.add(compute);
            p2Actions.add(request1);
            p2Actions.add(request2);
            p2Actions.add(compute);
            p2Actions.add(compute);
            p2Actions.add(free1);
            p2Actions.add(free2);
            p2Actions.add(halt);
            
        Queue<ProcessAction> p3Actions = new LinkedList<ProcessAction>(p2Actions);
        
        
        //System.out.println("Creating processes...");
        DeadlockProcess p1 = sim.createProcess(p1Actions);
        DeadlockProcess p2 = sim.createProcess(p2Actions);
        DeadlockProcess p3 = sim.createProcess(p3Actions);
        
        this.processesButton.setEnabled(true);
        this.runButton.setEnabled(true);
        this.stepButton.setEnabled(true);
        pack();
    }
    
    private void exitButtonActionPerformed(ActionEvent evt) 
    {
        System.exit(0);
    }

    private void runButtonActionPerformed(ActionEvent evt) 
    {
        java.util.List<DeadlockProcess> processList = sim.getProcesses();
        if (processList.isEmpty())
        {
            JOptionPane.showMessageDialog(this, "Please define at least one process for the simulation.");
        }
        else
        {
            pauseButton.setEnabled(true);
            stepButton.setEnabled(false);
            resetButton.setEnabled(true);
            processesButton.setEnabled(false);
            resourcesButton.setEnabled(false);
            runButton.setEnabled(false);            
            if(sim.getGlobalTime() == 0)
                sim.initActiveProcesses();
            sim.runSimulation();
        }
    }

    private void pauseButtonActionPerformed(ActionEvent evt) 
    {
        
         sim.stopSimulation();
         sim.sendMessage("Clock has been stopped.", false);
    }

    private void stepButtonActionPerformed(ActionEvent evt) 
    {   
        java.util.List<DeadlockProcess> processList = sim.getProcesses();
        if (processList.isEmpty())
        {
            JOptionPane.showMessageDialog(this, "Please define at least one process for the simulation.");
        }
        else
        {        
            resetButton.setEnabled(true);
            //runButton.setEnabled(false);
            //processesButton.setEnabled(false);
            //resourcesButton.setEnabled(false);
            pauseButton.setEnabled(false);        
            if(sim.getGlobalTime() == 0)
                sim.initActiveProcesses();
            sim.executeTimestep();
        }
    }

    private void resetButtonActionPerformed(ActionEvent evt) 
    {  
        sim.resetScenario();
        sim.refreshDisplay();
        pack();
    }

    private void startOverButtonActionPerformed(ActionEvent evt)
    {
        this.clearSimulator();
    }
    // End of variables declaration//GEN-END:variables
    private void processesButtonActionPerformed(ActionEvent evt) 
    {   //open ProcessEditorUI();
        Integer resourceCount = processEditorUI.buildResourceList(sim);
        if (resourceCount == 0)
        {
            JOptionPane.showMessageDialog(this, "Please define resources before defining processes.");
        }
        else
        {
            processEditorUI.setVisible(true);
            sim.getResourceDisplay();
        }
    }
    private void resourcesButtonActionPerformed(ActionEvent evt)
    {
        resourceEditorUI.setVisible(true);
        sim.getResourceDisplay();
        resourceEditorUI.setAlwaysOnTop(true);
    }
    private void helpButtonActionPerformed(ActionEvent evt) 
    {
        JOptionPane.showMessageDialog(this, "YEAH RIGHT! Click stuff." +
                "\n\nCreated in 2008 By:" +
                "\nJason Kabel" +
                "\nRafal Omilian"+
                "\nKaren Pelletier"+
                "\nChris Schmidt");
        // TODO add your handling code here:
    }

}
